package com.zucc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.zucc.controller.req.*;
import com.zucc.controller.resp.InventoryDetailResp;
import com.zucc.controller.resp.InventoryResp;
import com.zucc.entity.*;
import com.zucc.entity.base.MyMapper;
import com.zucc.exception.SyzxException;
import com.zucc.service.InventoryService;
import com.zucc.service.base.MyServiceImpl;
import com.zucc.service.base.PageData;
import com.zucc.util.MyBeanUtil;
import com.zucc.util.MyPageUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author : charspan
 * @Description :
 * @create : 2021-12-24 1:56 下午
 */
@Service
public class InventoryServiceImpl extends MyServiceImpl<Inventory> implements InventoryService {

    @Resource
    private InventoryMapper inventoryMapper;

    @Resource
    private InventoryDetailMapper inventoryDetailMapper;

    @Resource
    private UserMapper userMapper;

    @Override
    public MyMapper<Inventory> mapper() {
        return inventoryMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(InventoryAddReq req) {
        Inventory inventory = new Inventory();
        BeanUtil.copyProperties(req, inventory);
        inventory.setDelFlag(0);
        inventory.setCreateTime(DateUtil.date());
        inventory.setModifyTime(DateUtil.date());
        inventory.setStatus(0);
        super.saveKey(inventory);

        // 新增盘点详情
        List<InventoryDetail> inventoryDetails = new ArrayList<>();
        for (InventoryDetailAddReq item : req.getItems()) {
            InventoryDetail inventoryDetail = new InventoryDetail();
            inventoryDetail.setInventoryId(inventory.getId());
            inventoryDetail.setDeviceId(item.getDeviceId());
            inventoryDetail.setAddress(item.getAddress());
            inventoryDetail.setCount(item.getCount());
            inventoryDetail.setStatus(0);
            inventoryDetail.setDelFlag(0);
            inventoryDetail.setCreateTime(DateUtil.date());
            inventoryDetail.setModifyTime(DateUtil.date());
            inventoryDetails.add(inventoryDetail);
        }
        inventoryDetailMapper.insertList(inventoryDetails);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modify(InventoryModifyReq req) {
        Inventory inventoryExist = super.findById(req.getId());
        if (Objects.isNull(inventoryExist)) {
            throw new SyzxException("系统找不到相应编号的盘点计划信息");
        }

        if (inventoryExist.getStatus().intValue() != 0) {
            throw new SyzxException("当前盘点计划已无法进行修改（只有待执行的盘点计划才能进行调整）");
        }

        BeanUtil.copyProperties(req, inventoryExist, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        inventoryExist.setModifyTime(DateUtil.date());
        super.updateSelective(inventoryExist);

        if (req.getItems().isEmpty()) {
            return;
        }

        // 删除原有详情
        Example exp = new Example(InventoryDetail.class);
        exp.createCriteria().andEqualTo("inventoryId", req.getId());
        inventoryDetailMapper.deleteByExample(exp);

        // 新增盘点详情
        List<InventoryDetail> inventoryDetails = new ArrayList<>();
        for (InventoryDetailAddReq item : req.getItems()) {
            InventoryDetail inventoryDetail = new InventoryDetail();
            inventoryDetail.setInventoryId(req.getId());
            inventoryDetail.setDeviceId(item.getDeviceId());
            inventoryDetail.setAddress(item.getAddress());
            inventoryDetail.setCount(item.getCount());
            inventoryDetail.setStatus(0);
            inventoryDetail.setDelFlag(0);
            inventoryDetail.setCreateTime(DateUtil.date());
            inventoryDetail.setModifyTime(DateUtil.date());
            inventoryDetails.add(inventoryDetail);
        }
        inventoryDetailMapper.insertList(inventoryDetails);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOne(Long id) {
        Inventory inventoryExist = super.findById(id);
        if (Objects.isNull(inventoryExist)) {
            throw new SyzxException("系统找不到相应编号的盘点计划信息");
        }
        inventoryExist.setDelFlag(1);
        inventoryExist.setDeleteTime(DateUtil.date());
        super.updateSelective(inventoryExist);
    }

    @Override
    public InventoryResp detail(Long id) {
        Inventory inventoryExist = super.findById(id);
        if (Objects.isNull(inventoryExist)) {
            throw new SyzxException("系统找不到相应编号的盘点计划信息");
        }
        InventoryResp resp = new InventoryResp();
        BeanUtil.copyProperties(inventoryExist, resp);
        User user = userMapper.selectByPrimaryKey(resp.getUserId());
        if (Objects.isNull(user)) {
            throw new SyzxException("系统找不到相应编号的盘点人信息");
        }
        resp.setUserName(user.getName());

        Example exp = new Example(InventoryDetail.class);
        exp.createCriteria().andEqualTo("inventoryId", id);
        List<InventoryDetail> inventoryDetails = inventoryDetailMapper.selectByExample(exp);

        List<InventoryDetailResp> items = MyBeanUtil.converterList(inventoryDetails, InventoryDetailResp.class);
        resp.setItems(items);
        return resp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitSingleInventoryResult(InventoryResultDetailReq req) {
        InventoryDetail inventoryDetailExist = inventoryDetailMapper.selectByPrimaryKey(req.getId());
        if (Objects.isNull(inventoryDetailExist)) {
            throw new SyzxException("系统找不到相应编号的盘点计划详情信息");
        }
        BeanUtil.copyProperties(req, inventoryDetailExist, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        inventoryDetailExist.setModifyTime(DateUtil.date());
        inventoryDetailMapper.updateByPrimaryKey(inventoryDetailExist);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitInventoryResult(InventoryResultReq req) {
        req.getItems().forEach(this::submitSingleInventoryResult);
    }

    @Override
    public PageData<InventoryResp> page(InventorySearchReq req) {
        Example example = new Example(Inventory.class);
        example.setOrderByClause("modify_time DESC");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("delFlag", 0);
        if (Objects.nonNull(req.getType())) {
            criteria.andEqualTo("type", req.getType());
        }
        if (Objects.nonNull(req.getDate())) {
            criteria.andEqualTo("date", req.getDate());
        }
        if (Objects.nonNull(req.getUserId())) {
            criteria.andEqualTo("userId", req.getUserId());
        }
        if (StrUtil.isNotBlank(req.getRemarks())) {
            criteria.andLike("remarks", "%" + req.getRemarks() + "%");
        }
        PageData<Inventory> pageData = super.findByPage(req, example);
        PageData<InventoryResp> convert = MyPageUtil.convert(pageData, InventoryResp.class);

        List<Long> userIds = convert.getList().stream().map(InventoryResp::getUserId).distinct().collect(Collectors.toList());
        Example exp = new Example(User.class);
        exp.createCriteria().andIn("id", userIds);
        List<User> users = userMapper.selectByExample(exp);
        Map<Long, String> userMap = users.stream().collect(Collectors.toMap(User::getId, User::getName));

        for (InventoryResp inventoryResp : convert.getList()) {
            inventoryResp.setUserName(userMap.get(inventoryResp.getUserId()));
        }
        return convert;
    }

}